package model

import (
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"mail/app/config"
	"mail/app/utils"
)

/**
 * 构造函数, 得到实例
 */
func NewUser() *User {
	temp := &User{
	}

	return temp
}

/**
 * 登录验证
 */
func (u *User) Login(cont string) (data LoginData, err error) {
	data = LoginData{}
	config.GetLogger().Info("开始登录")

	user := new(ReceiveLogin)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("登录数据解析失败",
			"err", err.Error,
		)
		return data, err
	}

	//密码加密后验证

	userEmail := user.UserEmail
	userPwd := utils.EncodeMd5(user.UserPassword)

	//查询用户类型
	row := db.Table("users").Where("user_email = ? AND user_passwd = ?", userEmail, userPwd).
		Select("user_type, id").Row()

	err = row.Scan(&data.Type, &data.UserID)
	if err != nil {
		config.GetLogger().Warnw("用户名密码错误",
			"err", errors.New("用户名密码错误"),
		)
		return data, errors.New("用户名密码错误")
	}

	config.GetLogger().Info("登录结束")

	return data, err
}

/**
 * 用户注册
 */
func (u *User) Register(cont string) (err error) {
	count := 0

	config.GetLogger().Info("开始解析注册数据")
	user := new(Info)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return err
	}
	config.GetLogger().Info("解析注册数据结束")

	config.GetLogger().Info("开始注册")

	//邮箱不能重复
	count = 0
	db.Table("users").Where("user_email = ?", user.Email).Count(&count)

	//邮箱存在时
	if count != 0 {
		config.GetLogger().Warnw("注册失败",
			"err: ", errors.New("邮箱已存在"),
		)
		return errors.New("邮箱已存在")
	}

	//密码进行MD5加密
	i := new(Users)
	i.UserName = user.User
	i.UserPwd = utils.EncodeMd5(user.Password)
	i.UserType = 0
	i.UserEmail = user.Email
	i.SMTPStatus = "T"
	i.POPStatus = "T"

	//数据库中新建一个用户
	if err = db.Table("users").Create(&i).Error; err != nil {
		config.GetLogger().Warnw("注册失败",
			"err: ", err,
		)
		return
	}

	config.GetLogger().Info("注册结束")

	return
}

/**
 * 用户信息查询
 */
func (u *User) UserInfo(cont string) (User UserInfo, err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(UserID)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始获取用户信息")
	row := db.
		Table("users").
		Select("user_name, user_passwd, user_type, user_email, smtp_state, pop_state").
		Where("id = ?", user.UserID).Row()

	err = row.Scan(&User.UserName, &User.UserPwd, &User.UserType, &User.UserEmail, &User.SMTPStatus, &User.POPStatus)
	if err != nil {
		config.GetLogger().Warnw("获取用户信息失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("获取用户信息结束")

	return
}

/**
 * 发件箱
 */
func (u *User) UserSendBox(cont string) (SendBox []UserMails, err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(UserEmail)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始获取用户发件箱")
	rows, _ := db.
		Table("emails").
		Select("id, user_email, email_from, email_to, email_subject, email_content, email_size, email_time").
		Where("user_email = ?", user.UserEmail).
		Order("email_time").Rows()

	for rows.Next() {
		tempBox := new(UserMails)

		err = rows.Scan(&tempBox.EmailID, &tempBox.UserMail, &tempBox.EmailFrom, &tempBox.EmailTo, &tempBox.EmailSubject, &tempBox.EmailContent, &tempBox.EmailSize, &tempBox.EmailTime)
		if err != nil {
			config.GetLogger().Warnw("数据获取错误",
				"err:", err,
			)
			return
		}
		SendBox = append(SendBox, *tempBox)
	}
	config.GetLogger().Info("获取用户发件箱结束")

	return
}

/**
 * 回收站
 */
func (u *User) UserRecycleBox(cont string) (SendBox []UserMails, err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(UserEmail)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始获取用户回收站")
	rows, _ := db.
		Table("emails").
		Select("id, user_email, email_from, email_to, email_subject, email_content, email_size, email_time").
		Where("email_from = ? AND email_from_del = ?", user.UserEmail, "T").
		Order("email_time").Rows()

	for rows.Next() {
		tempBox := new(UserMails)

		err = rows.Scan(&tempBox.EmailID, &tempBox.UserMail, &tempBox.EmailFrom, &tempBox.EmailTo, &tempBox.EmailSubject, &tempBox.EmailContent, &tempBox.EmailSize, &tempBox.EmailTime)
		if err != nil {
			config.GetLogger().Warnw("数据获取错误",
				"err:", err.Error(),
			)
			return
		}
		SendBox = append(SendBox, *tempBox)
	}

	rows, _ = db.
		Table("emails").
		Select("id, user_email, email_from, email_to, email_subject, email_content, email_size, email_time").
		Where("email_to = ? AND email_to_del = ?", user.UserEmail, "T").
		Order("email_time").Rows()

	for rows.Next() {
		tempBox := new(UserMails)

		err = rows.Scan(&tempBox.EmailID, &tempBox.UserMail, &tempBox.EmailFrom, &tempBox.EmailTo, &tempBox.EmailSubject, &tempBox.EmailContent, &tempBox.EmailSize, &tempBox.EmailTime)
		if err != nil {
			config.GetLogger().Warnw("数据获取错误",
				"err:", err.Error(),
			)
			return
		}
		SendBox = append(SendBox, *tempBox)
	}
	config.GetLogger().Info("获取用户回收站结束")

	return
}

/**
 * 用户删除发件箱中邮件
 */
func (u *User) DeleteSentMail(cont string) (err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(DeleteSentMail)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始软删除发件箱邮件")
	err = db.Table("emails").
		Where("id = ?", user.MailID).
		Updates(map[string]interface{}{"email_from_del": "T"}).Error
	if err != nil {
		config.GetLogger().Warnw("邮件删除错误",
			"err:", err,
		)
		return
	}
	config.GetLogger().Info("软删除发件箱邮件结束")

	return
}

/**
 * 用户恢复回收站中邮件
 */
func (u *User) RecoverMail(cont string) (err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(DeleteSentMail)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始恢复回收站的邮件")
	from := ""
	to := ""
	row := db.Table("emails").
		Select("email_from, email_to").
		Where("id = ?", user.MailID).Row()

	err = row.Scan(&from, &to)
	if err != nil {
		config.GetLogger().Warnw("邮件错误",
			"err:", err,
		)
		return
	}

	if from == to {
		email := new(UserMail)
		err = db.Table("emails").Model(&email).
			Where("id = ? ", user.MailID).
			Updates(map[string]interface{}{"email_to_del": "F", "email_from_del": "F"}).Error
		if err != nil {
			config.GetLogger().Warnw("邮件恢复错误",
				"err:", err,
			)
			return
		}
	} else if user.Email == to {
		email := new(UserMail)
		err = db.Table("emails").Model(&email).
			Where("id = ?", user.MailID).
			Updates(map[string]interface{}{"email_to_del": "F"}).Error
		if err != nil {
			config.GetLogger().Warnw("邮件恢复错误",
				"err:", err,
			)
			return
		}
	} else if user.Email == from {
		email := new(UserMail)
		err = db.Table("emails").Model(&email).
			Where("id = ?", user.MailID).
			Updates(map[string]interface{}{"email_from_del": "F"}).Error
		if err != nil {
			config.GetLogger().Warnw("邮件恢复错误",
				"err:", err,
			)
			return
		}
	}
	config.GetLogger().Info("恢复回收站的邮件结束")

	return
}

/**
 * 用户清空回收站
 */
func (u *User) EmptyRecycleBox(cont string) (err error) {

	config.GetLogger().Info("开始解析数据")
	user := new(DeleteSentMail)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err: ", err,
		)
		return
	}
	config.GetLogger().Info("解析数据结束")

	config.GetLogger().Info("开始清空回收站")

	from := ""
	to := ""
	row := db.Table("emails").
		Select("email_from, email_to").
		Where("id = ?", user.MailID).Row()

	err = row.Scan(&from, &to)
	if err != nil {
		config.GetLogger().Warnw("邮件错误",
			"err:", err,
		)
		return
	}

	if user.Email == from {
		email := new(UserMail)
		err = db.Table("emails").Model(&email).
			Where("id = ?", user.MailID).
			Updates(map[string]interface{}{"email_from_del": "N"}).Error
		if err != nil {
			config.GetLogger().Warnw("邮件删除错误",
				"err:", err,
			)
			return
		}
	} else if user.Email == to {
		email := new(UserMail)
		err = db.Table("emails").Model(&email).
			Where("id = ?", user.MailID).
			Updates(map[string]interface{}{"email_to_del": "N"}).Error
		if err != nil {
			config.GetLogger().Warnw("邮件删除错误",
				"err:", err,
			)
			return
		}
	}
	config.GetLogger().Info("清空回收站结束")

	return
}

/**
 * 修改个人信息
 */
func (u *User) ChangeInfo(cont string) (err error) {
	i := new(Users)
	count := 0

	//接收前端所传数据并解析
	config.GetLogger().Info("开始解析数据")
	user := new(ReceiveChange)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err", err.Error(),
		)
		return err
	}
	config.GetLogger().Info("完成解析数据")

	//查询用户是否存在
	config.GetLogger().Info("开始获取个人信息")
	err = db.Table("users").Where("id = ?", user.UserID).Count(&count).Error
	if err != nil || count == 0 {
		config.GetLogger().Warnw("获取个人信息失败",
			"err", err,
		)
		return errors.New("获取个人信息失败")
	}
	config.GetLogger().Info("获取个人信息结束")

	config.GetLogger().Info("开始更新数据库数据")
	//开始更新
	err = db.
		Table("users").Model(&i).
		Where("id = ?", user.UserID).
		Updates(map[string]interface{}{"user_name": user.UserName}).Error
	if err != nil {
		config.GetLogger().Warnw("更新个人信息失败",
			"err", err,
		)
		return
	}
	config.GetLogger().Info("更新数据库数据结束")

	config.GetLogger().Info("更新个人信息结束")

	return
}

/**
 * 修改个人密码
 */
func (u *User) ChangePwd(cont string) (err error) {
	i := new(Users)
	count := 0
	temp := ""

	//接收前端所传数据并解析
	config.GetLogger().Info("开始解析数据")
	user := new(ReceiveChangePwd)
	err = json.Unmarshal([]byte(cont), &user)
	if err != nil {
		config.GetLogger().Warnw("数据解析失败",
			"err", err.Error(),
		)
		return err
	}
	config.GetLogger().Info("完成解析数据")

	//获取用户信息
	config.GetLogger().Info("开始获取个人信息")
	tempOldPwd := md5.Sum([]byte(user.OldPassword))
	md5str := fmt.Sprintf("%x", tempOldPwd)

	err = db.Table("users").Where("id = ? AND user_passwd = ?", user.UserID, md5str).Count(&count).Error
	if err != nil || count == 0 {
		config.GetLogger().Warnw("获取个人信息失败",
			"err", err,
		)
		return errors.New("获取个人信息失败")
	}
	config.GetLogger().Info("获取个人信息结束")

	//新密码不可与原密码重复
	config.GetLogger().Info("开始检验密码是否重复")
	tempNewPwd := md5.Sum([]byte(user.NewPassword))
	md5str = fmt.Sprintf("%x", tempNewPwd)

	row := db.Table("users").Where("id = ?", user.UserID).Select("user_passwd").Row()
	err = row.Scan(&temp)

	if err != nil {
		config.GetLogger().Warnw("检验密码是否重复失败",
			"err", err,
		)
		return
	}
	if temp == md5str {
		config.GetLogger().Warnw("新密码与原密码重复")
		return errors.New("新密码与原密码重复")
	}
	config.GetLogger().Info("检验密码是否重复结束")

	//更新密码
	config.GetLogger().Info("开始更新个人密码")
	i.UserPwd = md5str

	err = db.Table("users").Model(&i).
		Where("id = ?", user.UserID).
		Updates(map[string]interface{}{"user_passwd": i.UserPwd}).Error
	if err != nil {
		config.GetLogger().Warnw("更新个人密码失败",
			"err", err,
		)
		return
	}
	config.GetLogger().Info("更新个人密码结束")

	return
}
